home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Science / RLaB / rlib / plplot.r < prev    next >
Text File  |  1994-04-25  |  35KB  |  1,463 lines

  1. //-------------------------------------------------------------------//
  2. // plplot.r
  3.  
  4. // Syntax:    pstart ( NCOL, NROW, DEVICE )
  5. //        pwin ( NWIN )
  6. //        showpwin ( )
  7. //        pclose ( )
  8. //        pend ( )
  9. //        plot ( DATA )
  10. //        plhist ( DATA )
  11. //        xlabel ( XLABEL )
  12. //        ylabel ( YLABEL )
  13. //        ptitle ( PTITLE )
  14. //        plimits ( XMIN, XMAX, YMIN, YMAX, ZMIN, ZMAX )
  15. //        plgrid ( GRID_STY_X, GRID_STY_Y )
  16. //        plgrid3 ( GRID_STY_X, GRID_STY_Y, GRID_STY_Z )
  17. //        plaxis ( X_STR, Y_STR )
  18. //        plstyle ( PSTYLE )
  19.  
  20. //        plot3 ( L3D )
  21. //        zlabel ( ZLABEL )
  22. //        plalt ( ALT )
  23. //        plaz ( AZ )
  24.  
  25. //        plfont ( FONT )
  26. //        plwid ( WIDTH )
  27. //        plptex ( TEXT, X, Y, DX, DY, JUST )
  28.  
  29. //        plprint ( FILENM, DEVICE )
  30. //        replot ( )
  31.  
  32. // Description:
  33.  
  34. //    These function define a user interface to the PLPLOT grpahics
  35. //    library. The PLPLOT graphics library can produce output on
  36. //    X-windows, DOS, OS/2, Amiga, Tektronicks, postscipt, and other
  37. //    output devices.
  38.  
  39. //    The plot interface operation is based upon two important
  40. //    concepts: the current plot-window, and the current sub-plot.
  41.  
  42. //    The current plot-window is a valid concept only if selected
  43. //    output device supports multiple windows (X-windows for
  44. //    example). 
  45.  
  46. //    The current sub-plot should be available for all devices,
  47. //    since sub-plots are individual plots that co-exist on the same
  48. //    page, or display.
  49.  
  50. //    Invoking pstart() will create a plot-window. The newly created
  51. //    plot-window will be the current plot-window. If more than one
  52. //    plot-window has been created, then the current window can be
  53. //    selected with the pwin() function. The current plot-window can
  54. //    be closed with pclose(). All of the plot-windows can be closed
  55. //    with pend().
  56.  
  57. //    Each plot-window can be divided up into more than 1 sub-plot
  58. //    (the default). The number and arrangement of the sub-plots is
  59. //    specified by the user when pstart() is invoked. All plot
  60. //    manipulation functions, such as ptyle(), pgrid(), xlabel(),
  61. //    etc... work on the current sub-plot. When plot() is used the
  62. //    current sub-plot is created, and the current sub-plot is
  63. //    incremented. the sub-plots are incremented to the right, and
  64. //    down (the same way you read a English language book).
  65.  
  66. //    pstart ( NCOL, NROW, DEVICE )
  67.  
  68. //        Create a plot-window. The newly created plot-windown
  69. //        becomes the current plot-window with NCOLxNROW
  70. //        sub-plots. DEVICE specifies the output device type. If
  71. //        DEVICE is not specified, then the user is provided
  72. //        with a menu of options. All arguments are optional.
  73. //        This function MUST be used before any plotting can
  74. //        occur. 
  75.  
  76. //    pwin ( N )
  77.  
  78. //        Switch the current plot-window to plot-window N.
  79.  
  80. //    pclose ( )
  81.  
  82. //        Close the current plot-window. The new current
  83. //        plot-window is the remaining plot-window with the
  84. //        lowest tag value.
  85.  
  86. //    pend ( )
  87.  
  88. //        End the current plotting session. Closes all
  89. //        plot-windows.
  90.  
  91. //    plot ( DATA )
  92.  
  93. //        Plot DATA in the current sub-plot in the current
  94. //        plot-window. DATA can consist of either a matrix, in
  95. //        which case the columns are plotted against the 1st
  96. //        column. DATA can also consist of a list, in which case
  97. //        each matrix in the list is plotted (this is a good way
  98. //        to plot data with different scales). 
  99.  
  100. //    plhist ( DATA , NBIN )
  101.  
  102. //        Plot a histogram of the data in DATA. DATA can be a
  103. //        N-column matrix. The columns of DATA are plotted in
  104. //        histogram fashion. An optional second argument, NBIN
  105. //        specifies the number of bins to separate the data
  106. //        into. If NBIN is not specifies the default is 10.
  107.  
  108. //    xlabel ( XLABEL )
  109.  
  110. //        Set the x-axis label for the current sub-plot in the
  111. //        current plot-window. If xlabel is used without any
  112. //        arguments, then the x-axis label is set to the
  113. //        null-string. 
  114.  
  115. //    ylabel ( YLABEL )
  116.  
  117. //        Set the y-axis label for the current sub-plot in the
  118. //        current plot-window.
  119.  
  120. //    ptitle ( PTITLE )
  121.  
  122. //        Set the title for the current sub-plot in the current
  123. //        plot-window. 
  124.  
  125. //    plimits ( XMIN, XMAX, YMIN, YMAX, ZMIN, ZMAX )
  126.  
  127. //        Set the scale limits of the current sub-plot in the
  128. //        current plot-window. If any of the arguments are
  129. //        omitted, then the corresponding scale limit is
  130. //        determined from the data.
  131.  
  132. //    plgrid ( GRID_STY_X, GRID_STY_Y )
  133.  
  134. //        Set the grid type for the current sub-plot in the
  135. //        curent plot-window. The grid type is specified by a
  136. //        string. The possible elements of the string are
  137. //        described below. The string can include any
  138. //        combination of the following letters (lower case) in
  139. //        any order. If plgrid is called without any
  140. //        arguments, the defaults are reset.
  141.  
  142. //        a    Draws axis, X-axis is horizontal line 
  143. //            (at y=0), and Y-axis is vertical line (at x=0).
  144.  
  145. //        b    Draws bottom (X) or left (Y) edge of frame.
  146. //        c    Draws top (X) or right (Y) edge of frame.
  147. //        g    Draws a grid at the major tick interval.
  148. //        i    Inverts tick marks, so they are drawn
  149. //            outwards, rather than inwards.
  150. //        l    Scales axis logarithmithecally.
  151. //        m    Writes numeric labels at major tick intervals 
  152. //            in the unconventional location 
  153. //            (above box for X, right of box for Y).
  154. //        n    Writes numeric labels at major tick intervals 
  155. //            in the conventional location 
  156. //            (below box for X, left of box for Y).
  157. //        s    Enables subticks between major ticks, only
  158. //            valid if "t" is also specified.
  159. //        t    Draws major ticks.
  160.  
  161. //        Example - Set X and Y logarithmic scales:
  162.  
  163. //            plgrid ( "bcgnstl", "bcgnstlv")
  164.   
  165.  
  166. //    plaxis ( X_STR, Y_STR )
  167.  
  168. //        An friendlier interface to the axis styles. Currently
  169. //        plaxis only supports the default and a predefined
  170. //        logarithmic axis styles. X_STR and/or Y_STR can be
  171. //        either "log" or "", or omitted. If the string "log" is
  172. //        used for either argument, then that axis is scaled
  173. //        logarithmically. Otherwise, the default axis style is
  174. //        used .
  175.  
  176. //        Example: plaxis ("log", "log")
  177.  
  178. //    plgrid3 ( GRID_STY_X, GRID_STY_Y, GRID_STY_Z )
  179.  
  180. //        Set the grid type for the current sub-plot in the
  181. //        curent plot-window. The grid type is specified by a
  182. //        string. The possible elements of the string are
  183. //        described below. The string can include any
  184. //        combination of the following letters (lower case) in
  185. //        any order. If plgrid3 is called without any
  186. //        arguments, the defaults are reset.
  187.  
  188. //        b    Draws axis at base, at height 
  189. //            (z=zmin). This character must be specified
  190. //            in order to use any of the other options.
  191. //        i    Inverts tick marks, so they are drawn
  192. //            downwards, rather than upwards.
  193. //        l    Scale axis logarithmically. 
  194. //        n    Writes numeric labels at major tick intervals.
  195. //        s    Enables subticks between major ticks, only 
  196. //            valid if "t" is also specified.
  197. //        t    Draws major ticks.
  198. //        u    If this is specified, the text label for the 
  199. //            axis is written under the axis.
  200.  
  201. //    plstyle ( STYLE )
  202.  
  203. //        Plstyle controls the line-style for 2-dimensional
  204. //        graphs. STYLE can be: "line", "point", and
  205. //        "line-point". In the future plstyle will accept a
  206. //        vector of style strings so that different lines can
  207. //        have different styles within the same graph.
  208.  
  209. //    plot3 ( L1, L2, L3 )
  210.  
  211. //        Plot3 creates a 3-dimensional surface plot from the
  212. //        data in lists L1, L2, L3 (L2 and L3 are optional). The
  213. //        list must contain elemenst `x', `y', and `z'. the z
  214. //        element is a rectangular matrix that is a function of
  215. //        x and y (z[i;j] = f(x[i],y[j])). Up to 3 lists, or
  216. //        surface plots can be created on the same sub-plot.
  217.  
  218. //    zlabel ( ZLABEL )
  219.  
  220. //        Set the z-axis label for the current sub-plot in the
  221. //        current plot-window. If zlabel is used without any
  222. //        arguments, then the z-axis label is set to the
  223. //        null-string. 
  224.  
  225. //    plalt ( ALT )
  226.  
  227. //        Set the "altitude" for the current sub-plot in the
  228. //        current plot-window. The viewing altitude in degrees
  229. //        above the XY plane. Only affects 3D plots.
  230.  
  231. //    plaz ( AZ )
  232.  
  233. //        Set the "azimuth" for the current sub-plot in the
  234. //        current plot-window. Azimuth represents the viewing
  235. //        angle in degrees. When AZ=0, the observer is looking
  236. //        face onto the ZX plane, and as AZ is increased, the
  237. //        observer moves clockwise around the box when viewed
  238. //        from above the XY plane. Only affects 3D plots.
  239.  
  240. //    plfont ( FONT )
  241.  
  242. //        Change to font-style FONT.
  243.  
  244. //        FONT 1:    Normal (simplest and fastest)
  245. //             2: Roman font
  246. //             3: Italic font
  247. //             4: Script font
  248.  
  249. //    plwid ( WIDTH )
  250.  
  251. //        Change the pen width to WIDTH. The result is device
  252. //        dependent. For some devices, such as postscipt, WIDTH
  253. //        must be > 0 and <= 10.
  254.  
  255. //    plptex ( TEXT, X , Y , DX , DY , JUST )
  256.  
  257. //        Place TEXT in the plot window. 
  258. //        X: Specify the X coordinate for text placement.
  259. //        Y: Specify the Y coordinate for text placement.
  260. //        DX: X + DX specifies the X orientation of the text.
  261. //        DY: Y + DY specifies the Y orientation of the text.
  262. //        JUST: Specifies the position of the string relative to
  263. //        its reference point. If JUST=0, the reference point is
  264. //        at the left  and if JUST=1 it is at the right of the
  265. //        string. Other values of JUST give intermediate
  266. //        justifications. Since plptex uses the plot-data
  267. //        coordinates for text placement, plptex must be called
  268. //        AFTER the plot is created.
  269.  
  270. //    plprint ( FILENM , DEVICE )
  271.  
  272. //        Print the contents of the current plot-window to the
  273. //        PLPLOT device identified by the string DEVICE (the
  274. //        default is black and white Postscript if DEVICE is
  275. //        omitted). Options are:
  276. //            "ps"        Postscript (default)
  277. //            "psc"        Color Postscript
  278. //            "xfig"        Xfig file format
  279. //            "plmeta"    Plplot meta-file
  280. //            "ljii"        HP LaserJet II
  281.  
  282. //    replot ( )
  283.  
  284. //        Re-draws the current plot-window.
  285.  
  286. //-------------------------------------------------------------------//
  287.  
  288.  
  289. #
  290. # New plot.r for use with PLPLOT library.
  291. #
  292.  
  293.  static (WIN)            # The static plot window structure
  294.  static (P)            # The active/current plot window
  295.  
  296.  static (create_plot_object)
  297.  static (check_plot_object)
  298.  static (xy_scales)
  299.  static (xyz_scales)
  300.  static (list_scales)
  301.  static (hist_scales)
  302.  static (plot_matrix)
  303.  static (plot_list)
  304.  static (check_3d_list)
  305.  static (find_char)
  306.  
  307. #
  308. # Defaults
  309. #
  310.   static (grid_x_default, grid_y_default)
  311.   static (grid_3x_default, grid_3y_default, grid_3z_default)
  312.  
  313.   grid_x_default = "bcgnst";
  314.   grid_y_default = "bcgnstv";
  315.   grid_3x_default = "bnstu";
  316.   grid_3y_default = "bnstu";
  317.   grid_3z_default = "bcdmnstuv";
  318.  
  319. #
  320. # Create the default plot-object.
  321. # Initialize to all the default values
  322. #
  323.  
  324.  WIN = <<>>;    # Create the plot-object list
  325.  
  326.  create_plot_object = function ( N, nx, ny )
  327.  {
  328.    local (i, j, pobj)
  329.  
  330.    if (!exist (N)) { N = 0; }
  331.  
  332.    pobj = <<>>;
  333.    pobj.subplot = 0;        # The current subplot no.
  334.    pobj.nplot = nx*ny;        # Total no. of plots on window
  335.  
  336.    pobj.fontld = 0;        # Loaded extended fonts?
  337.  
  338.    for (i in 1:(nx*ny))
  339.    {
  340.      pobj.style[i] = "line";    # The type/style of plot to draw
  341.      pobj.pstyle[i] = 1;    # The point-style
  342.      pobj.nbin[i] = inf();    # The number of bins for a histogram
  343.      pobj.width[i] = 1;        # The pen width for current plot
  344.      pobj.font[i] = 1;        # The current font
  345.      pobj.xlabel[i] = "";
  346.      pobj.ylabel[i] = "";
  347.      pobj.zlabel[i] = "";
  348.      pobj.title[i] = "";
  349.      pobj.orientation[i] = "portrait";
  350.      pobj.gridx[i] =  grid_x_default;    # Plot axes style, 2D-X
  351.      pobj.gridy[i] =  grid_y_default;    # Plot axes style, 2D-Y
  352.      pobj.grid3x[i] = grid_3x_default;    # Plot axes style, 3D-X
  353.      pobj.grid3y[i] = grid_3y_default;    # Plot axes style, 3D-Y
  354.      pobj.grid3z[i] = grid_3z_default;    # Plot axes style, 3D-Z
  355.      pobj.aspect[i] = 0;        # Plot aspect style
  356.      pobj.alt[i] = 60;
  357.      pobj.az[i] = 45;
  358.  
  359.      pobj.xmin[i] = inf();
  360.      pobj.xmax[i] = inf();
  361.      pobj.ymin[i] = inf();
  362.      pobj.ymax[i] = inf();
  363.      pobj.zmin[i] = inf();
  364.      pobj.zmax[i] = inf();
  365.      
  366.      for (j in 1:14) { pobj.color[i;j] = j; }       
  367.      for (j in 1:8)  { pobj.lstyle[i;j] = j; }
  368.    }
  369.  
  370.    #
  371.    # Save and return the newly generated plot-object
  372.    #
  373.  
  374.    WIN.[N] = pobj;
  375.    return WIN.[N];
  376.  };
  377.  
  378. #
  379. # Check to make sure a plot-object exists. If one
  380. # does not exist, create it.
  381. #
  382.  
  383.  check_plot_object = function ()
  384.  {
  385.    if (length (WIN) == 0)
  386.    {
  387.      pstart();
  388.      return 0;
  389.    }
  390.    return 1;
  391.  };
  392.  
  393. #
  394. # Set the current plot window
  395. # Default value = 0
  396. #
  397.  
  398.  pwin = function ( N )
  399.  {
  400.    check_plot_object ();
  401.    if (!exist (N)) { N = 0; }
  402.  
  403.    # Check to make sure N is valid
  404.  
  405.    for (i in members (WIN))
  406.    {
  407.      if (N == strtod (i))
  408.      {
  409.        _plsstrm (N);
  410.        return P = N;
  411.      }
  412.    }
  413.    printf ("pwin: invalid argument, N = %i\n", N);
  414.    printf ("      valid values are:\n");
  415.    WIN?
  416.  };
  417.  
  418.  showpwin = function ()
  419.  {
  420.    check_plot_object ();
  421.  
  422.    printf ("Curren plot-window is: %i\n", P);
  423.    printf ("Available plot windows are:\n");
  424.    WIN?
  425.  };
  426.  
  427. #
  428. # Set/start/select the plot device
  429. #
  430.  
  431.  pstart = function ( nx, ny, dev )
  432.  {
  433.    if (!exist (nx)) { nx = 1; }
  434.    if (!exist (ny)) { ny = 1; }
  435.    if (!exist (dev)) { dev = "?"; }
  436.  
  437.    # Create the plot-object
  438.    # First, figure out the index
  439.    if (!exist (P))
  440.    {
  441.      P = 0;
  442.    else
  443.      P = P + 1;
  444.    }
  445.    create_plot_object (P, nx, ny);
  446.    _plsstrm (P);
  447.  
  448.    # Default window size for X
  449.    _plspage (0, 0, 400, 300, 200, 200);
  450.  
  451.    # Start up the plot-window
  452.    _plstart (dev, nx, ny);
  453.  
  454.    _plwid (8);
  455.  
  456.    # Turn between plot pause off
  457.    _plspause (0);
  458.    _pltext ();
  459.  
  460.    return P;
  461.  };
  462.  
  463.  #
  464.  # Close a plot device. We must destroy the current plot-object
  465.  # And switch the output stream back to the default.
  466.  #
  467.  
  468.  pclose = function ()
  469.  {
  470.    local (n)
  471.    if (size (WIN) > 1)
  472.    {   
  473.      clear (WIN.[P]);
  474.      _plend1 ();
  475.      _plsstrm (strtod (members (WIN)[1]));
  476.      P = strtod (members (WIN)[1]);
  477.    else
  478.      if (exist (WIN.[P])) { clear (WIN.[P]); }
  479.      _plend1 ();
  480.    }
  481.  };
  482.  
  483.  #
  484.  # Close ALL the plot-windows
  485.  #
  486.  
  487.  pend = function ()
  488.  {
  489.    _plend ();
  490.    if (exist (WIN)) { clear (WIN); }
  491.    if (exist (P)) { clear (P); }
  492.    WIN = <<>>;
  493.  };
  494.  
  495.  ##############################################################################
  496.  #
  497.  # Plot the columns of a matrix (X-Y plot).
  498.  #
  499.  ##############################################################################
  500.  
  501.  plot = function ( data )
  502.  {
  503.    local (hscale, xmin, xmax, ymin, ymax, i, p)
  504.   
  505.    check_plot_object ();
  506.  
  507.    p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;    # The current index
  508.  
  509.    #
  510.    # Draw the graph
  511.    # Step through the matrix plotting
  512.    # each column versus the 1st
  513.    #
  514.  
  515.    if (class (data) == "num")
  516.    {
  517.      _plgra ();
  518.      _plcol (1);
  519.      _pllsty (1);
  520.      _plfont (WIN.[P].font[p]);
  521.      _plwid (WIN.[P].width[p]);
  522.      xy_scales ( real(data), p, xmin, xmax, ymin, ymax );
  523.  
  524.      _pladv (0);
  525.      _plvsta ();
  526.      _plwind (xmin, xmax, ymin, ymax);
  527.      _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
  528.      if (plot_matrix ( data, p, 0 ) < 0) { return -1; }
  529.  
  530.    else if (class (data) == "list") {
  531.  
  532.      _plgra ();
  533.      _plcol (1);
  534.      _pllsty (1);
  535.      _plfont (WIN.[P].font[p]);
  536.      _plwid (WIN.[P].width[p]);
  537.      list_scales ( data , p, xmin, xmax, ymin, ymax );
  538.      _pladv (0);
  539.      _plvsta ();
  540.      _plwind (xmin, xmax, ymin, ymax);
  541.      _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
  542.      if (plot_list ( data, p ) < 0) { return -1; }
  543.  
  544.    else
  545.      error ("plot: un-acceptable argument");
  546.    }}
  547.  
  548.    _plcol (1);
  549.    _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);  
  550.    _plflush ();
  551.    _pltext ();
  552.  
  553.    #
  554.    # Increment the plot no. so that next time
  555.    # we use the correct settings.
  556.    #
  557.  
  558.    WIN.[P].subplot = WIN.[P].subplot + 1;
  559.    return P;
  560.  };
  561.  
  562.  ##############################################################################
  563.  #
  564.  # Plot a 3-Dimensional graph. The data is composed in a list, with
  565.  # elements `x', `y', and `z'. x and y are single-dimension arrays
  566.  # (row or column matrices), and z is a two-dimensional array. The
  567.  # array z, is a function of x and y: z = f(x,y). Thus, the values in
  568.  # the array x can be thought of a "row-labels", and the values of y
  569.  # can be thought of as "column-lables" for the 2-dimensioal array z.
  570.  #
  571.  # At present plot3 can plot 3 distinct lists. Each list may have
  572.  # different X, Y, and Z scales.
  573.  #
  574.  ##############################################################################
  575.  
  576.  plot3 = function ( L31, L32, L33 )
  577.  {
  578.    local (p, xmin, xmax, ymin, ymax, zmin, zmax, basex, basey, height, ...
  579.           xmin2d, xmax2d, ymin2d, ymax2d, alt, az, ...
  580.           Xmin, Xmax, Ymin, Ymax, Zmin, Zmax)
  581.  
  582.    check_plot_object ();
  583.  
  584.    #
  585.    # 1st check list contents
  586.    #
  587.  
  588.    if (exist (L31)) { check_3d_list (L31); }
  589.    if (exist (L32)) { check_3d_list (L32); }
  590.    if (exist (L33)) { check_3d_list (L33); }
  591.  
  592.    p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;    # The current index
  593.  
  594.    #
  595.    # Figure out the scale limits. 
  596.    # Needs improvement!
  597.    #
  598.  
  599.    xmin = xmax = ymin = ymax = zmin = zmax = 0;
  600.    if (exist (L31)) 
  601.    {
  602.      xyz_scales (L31, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
  603.      if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
  604.      if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
  605.      if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
  606.    }
  607.    if (exist (L32)) 
  608.    {
  609.      xyz_scales (L32, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
  610.      if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
  611.      if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
  612.      if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
  613.    }   
  614.    if (exist (L33)) 
  615.    {
  616.      xyz_scales (L33, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
  617.      if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
  618.      if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
  619.      if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
  620.    }
  621.  
  622.    _plgra ();
  623.    _plcol (1);
  624.    _pllsty (1);
  625.    _plfont (WIN.[P].font[p]);
  626.    _plwid (WIN.[P].width[p]);
  627.  
  628.    basex = 2; basey = 2; height = 4;
  629.    xmin2d = -2.0; xmax2d = 2.0;
  630.    ymin2d = -2.5; ymax2d = 5.0;
  631.  
  632.    _plenv (xmin2d, xmax2d, ymin2d, ymax2d, 0, -2);
  633.    _plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
  634.            zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
  635.    _plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
  636.             WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
  637.             WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
  638.    _plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
  639.  
  640.    if (exist (L31))
  641.    {
  642.      _plcol (2);
  643.      _plot3d (real(L31.x), real(L31.y), real(L31.z), ...
  644.               L31.x.n, L31.y.n, 3, 0);
  645.    }
  646.    if (exist (L32))
  647.    {
  648.      _plcol (3);
  649.      _pllsty (2);
  650.      _plot3d (real(L32.x), real(L32.y), real(L32.z), ...
  651.               L32.x.n, L32.y.n, 3, 0);
  652.    }
  653.    if (exist (L33)) 
  654.    {
  655.      _plcol (4);
  656.      _pllsty (3);
  657.      _plot3d (real(L33.x), real(L33.y), real(L33.z), ...
  658.               L33.x.n, L33.y.n, 3, 0);
  659.    }
  660.  
  661.    _plflush ();
  662.    _pltext ();
  663.  
  664.    #
  665.    # Increment the plot no. so that next time
  666.    # we use the correct settings.
  667.    #
  668.  
  669.    WIN.[P].subplot = WIN.[P].subplot + 1;
  670.  
  671.    return P;
  672.  };
  673.  
  674.  ##############################################################################
  675.  #
  676.  # Plot a Histogram(s), from the columns of a matrix.
  677.  #
  678.  ##############################################################################
  679.  
  680.  plhist = function ( M , nbin )
  681.  {
  682.    local (i, k, np, p)
  683.  
  684.    check_plot_object ();
  685.  
  686.    if (!exist (nbin)) { nbin = 10; }
  687.  
  688.    p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;    # The current index
  689.    np = M.nr;
  690.  
  691.    # Compute max/min values of data
  692.  
  693.    ymin = min (real (M));
  694.    ymax = max (real (M));
  695.  
  696.    #
  697.    # Check computed scale limits against user's
  698.    #
  699.  
  700.    if (!isinf (WIN.[P].ymin[p])) { ymin = WIN.[P].ymin[p]; }
  701.    if (!isinf (WIN.[P].ymax[p])) { ymax = WIN.[P].ymax[p]; }
  702.  
  703.    _plgra ();
  704.    _plcol (1);
  705.    _plfont (WIN.[P].font[p]);
  706.    _plwid (WIN.[P].width[p]);
  707.  
  708.    for (i in 1:M.nc) 
  709.    { 
  710.      hscale[i] = hist_scales (M[;i], nbin);
  711.    }  
  712.  
  713.    _pladv (0);
  714.    _plvsta ();
  715.    _plwind (ymin, ymax, 0, max (hscale));
  716.    _plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
  717.  
  718.    for (i in 1:M.nc)
  719.    {
  720.      k = mod (i, 14) + 1;
  721.      _plcol (WIN.[P].color[p;k]);
  722.      _plhist (np, real(M[;i]), ymin, ymax, nbin, 1);
  723.    }
  724.  
  725.    _plcol (1);
  726.    _pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);  
  727.    _plflush ();
  728.    _pltext ();
  729.  
  730.    #
  731.    # Increment the plot no. so that next time
  732.    # we use the correct settings.
  733.    #
  734.  
  735.    WIN.[P].subplot = WIN.[P].subplot + 1;
  736.  
  737.    return 1;
  738.  };
  739.  
  740.  ##############################################################################
  741.  #
  742.  # Various support functions for the WIN list
  743.  #
  744.  ##############################################################################
  745.  
  746.  #
  747.  # Replot
  748.  #
  749.  
  750.  replot = function ( )
  751.  {
  752.    check_plot_object ();
  753.    _replot ();
  754.  };
  755.  
  756.  #
  757.  # Set the X-axis label
  758.  #
  759.  
  760.  xlabel = function ( xstr )
  761.  {
  762.    local (i);
  763.  
  764.    check_plot_object ();
  765.    if (!exist (xstr)) { xstr = ""; }
  766.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  767.    WIN.[P].xlabel[i] = xstr;
  768.  };
  769.  
  770.  #
  771.  # Set the Y-axis label
  772.  #
  773.  
  774.  ylabel = function ( xstr )
  775.  {
  776.    local (i);
  777.  
  778.    check_plot_object ();
  779.    if (!exist (xstr)) { xstr = ""; }
  780.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  781.    WIN.[P].ylabel[i] = xstr;
  782.  };
  783.  
  784.  #
  785.  # Set the Z-axis label
  786.  #
  787.  
  788.  zlabel = function ( xstr )
  789.  {
  790.    local (i);
  791.  
  792.    check_plot_object ();
  793.    if (!exist (xstr)) { xstr = ""; }
  794.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  795.    WIN.[P].zlabel[i] = xstr;
  796.  };
  797.  
  798.  #
  799.  # Set the plot-title
  800.  #
  801.  
  802.  ptitle = function ( xstr )
  803.  {
  804.    local (i);
  805.  
  806.    check_plot_object ();
  807.    if (!exist (xstr)) { xstr = ""; }
  808.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  809.    WIN.[P].title[i] = xstr;
  810.  };
  811.  
  812.  plimits = function ( xmin, xmax, ymin, ymax, zmin, zmax )
  813.  {
  814.    local (i);
  815.  
  816.    check_plot_object ();
  817.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  818.    if (exist (xmin)) {
  819.      WIN.[P].xmin[i] = xmin;
  820.    else
  821.      WIN.[P].xmin[i] = inf ();
  822.    }
  823.    if (exist (xmax)) { 
  824.      WIN.[P].xmax[i] = xmax;
  825.    else
  826.      WIN.[P].xmax[i] = inf ();
  827.    }
  828.    if (exist (ymin)) {
  829.      WIN.[P].ymin[i] = ymin;
  830.    else
  831.      WIN.[P].ymin[i] = inf ();
  832.    }
  833.    if (exist (ymax)) {
  834.      WIN.[P].ymax[i] = ymax;
  835.    else
  836.      WIN.[P].ymax[i] = inf ();
  837.    }
  838.    if (exist (zmin)) {
  839.      WIN.[P].zmin[i] = zmin;
  840.    else
  841.      WIN.[P].zmin[i] = inf ();
  842.    }
  843.    if (exist (zmax)) {
  844.      WIN.[P].zmax[i] = zmax;
  845.    else
  846.      WIN.[P].zmax[i] = inf ();
  847.    }
  848.  };
  849.  
  850.  plgrid = function ( sty_x, sty_y )
  851.  {
  852.    local (i)
  853.  
  854.    check_plot_object ();
  855.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  856.  
  857.    if (exist (sty_x)) 
  858.    { 
  859.      if (class (sty_x) == "string")
  860.      {
  861.        WIN.[P].gridx[i] = sty_x;
  862.      else
  863.        error ("plgrid: requires string argument GRID_STY_X");
  864.      }
  865.    else
  866.      WIN.[P].gridx[i] = grid_x_default;
  867.    }
  868.    if (exist (sty_y)) 
  869.    { 
  870.      if (class (sty_y) == "string")
  871.      {
  872.        WIN.[P].gridy[i] = sty_y;
  873.      else
  874.        error ("plgrid: requires string argument GRID_STY_Y");
  875.      }
  876.    else
  877.      WIN.[P].gridy[i] = grid_y_default;
  878.    }
  879.  };
  880.  
  881.  plgrid3 = function ( sty_x, sty_y, sty_z )
  882.  {
  883.    local (i)
  884.  
  885.    check_plot_object ();
  886.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  887.    if (exist (sty_x)) 
  888.    { 
  889.      if (class (sty_x) == "string")
  890.      {
  891.        WIN.[P].grid3x[i] = sty_x;
  892.      else
  893.        error ("plgrid3: requires string argument GRID_STY_X");
  894.      }
  895.    else
  896.      WIN.[P].grid3x[i] = grid_3x_default;
  897.    }
  898.    if (exist (sty_y)) 
  899.    { 
  900.      if (class (sty_y) == "string")
  901.      {
  902.        WIN.[P].grid3y[i] = sty_y;
  903.      else
  904.        error ("plgrid3: requires string argument GRID_STY_Y");
  905.      }
  906.    else
  907.      WIN.[P].grid3y[i] = grid_3y_default;
  908.    }
  909.    if (exist (sty_z)) 
  910.    { 
  911.      if (class (sty_z) == "string")
  912.      {
  913.        WIN.[P].grid3z[i] = sty_z;
  914.      else
  915.        error ("plgrid3: requires string argument GRID_STY_Z");
  916.      }
  917.    else
  918.      WIN.[P].grid3z[i] = grid_3z_default;
  919.    }
  920.  };
  921.  
  922.  #
  923.  # A friendlier interface to changing grid/axis
  924.  # styles.
  925.  #
  926.  
  927.  plaxis = function ( X_STR, Y_STR )
  928.  {
  929.    local (i)
  930.  
  931.    check_plot_object ();
  932.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  933.  
  934.    if (exist (X_STR))
  935.    {
  936.      if (X_STR == "log") { WIN.[P].gridx[i] = "bcngstl"; }
  937.    else
  938.      WIN.[P].gridx[i] = grid_x_default;
  939.    }
  940.  
  941.    if (exist (Y_STR))
  942.    {
  943.      if (Y_STR == "log") { WIN.[P].gridy[i] = "bcngstlv"; }
  944.    else
  945.      WIN.[P].gridy[i] = grid_y_default;
  946.    }
  947.    return P;
  948.  };
  949.  
  950.  #
  951.  # Change plot aspect ratio
  952.  #
  953.  
  954.  plaspect = function ( style )
  955.  {
  956.    local (i)
  957.  
  958.    check_plot_object ();
  959.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  960.    if (exist (style)) { WIN.[P].aspect[i] = style; }
  961.  };
  962.  
  963.  #
  964.  # Change plot line style
  965.  #
  966.  
  967.  plstyle = function ( style )
  968.  {
  969.    local (i)
  970.  
  971.    check_plot_object ();
  972.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  973.    if (exist (style)) { 
  974.      if (class (style) == "string") 
  975.      {
  976.        if (style == "line") {
  977.          WIN.[P].style[i] = "line";
  978.        else if (style == "point") {
  979.          WIN.[P].style[i] = "point";
  980.        else if (style == "line-point") {
  981.          WIN.[P].style[i] = "line-point";
  982.        }}}
  983.      }
  984.      return 1;
  985.    }
  986.    WIN.[P].style[i] = "line";  
  987.  };
  988.  
  989.  #
  990.  # Change fonts
  991.  #
  992.  
  993.  plfont = function ( font )
  994.  {
  995.    local (i)
  996.  
  997.    check_plot_object ();
  998.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  999.  
  1000.    if (!exist (font)) { font = 1; }
  1001.  
  1002.    if (WIN.[P].fontld == 0)
  1003.    {
  1004.      _plfontld (1);
  1005.      WIN.[P].fontld = 1;
  1006.    }
  1007.  
  1008.    WIN.[P].font[i] = font;
  1009.    return P;
  1010.  };
  1011.  
  1012.  #
  1013.  # Change pen width
  1014.  #
  1015.  
  1016.  plwid = function ( width )
  1017.  {
  1018.    local (i)
  1019.  
  1020.    check_plot_object ();
  1021.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  1022.  
  1023.    if (!exist (width)) { width = 1; }
  1024.    WIN.[P].width[i] = width;
  1025.    return P;
  1026.  };
  1027.  
  1028.  #
  1029.  # Place some text on the plot
  1030.  #
  1031.  
  1032.  plptex = function ( text, x , y , dx , dy , just )
  1033.  {
  1034.    if (!check_plot_object ()) {
  1035.      printf ("Must use plot() before plptex()\n");
  1036.      return 0;
  1037.    }
  1038.  
  1039.    if (!exist (x)) { x = 0; }
  1040.    if (!exist (y)) { y = 0; }
  1041.    if (!exist (dx)) { dx = x+1; }
  1042.    if (!exist (dy)) { dy = 0; }
  1043.    if (!exist (just)) { just = 0; }
  1044.  
  1045.    _plptex (x, y, dx, dy, just, text);
  1046.  };
  1047.  
  1048.  #
  1049.  # Set up the viewing altitude for 3-D plots
  1050.  #
  1051.  
  1052.  plalt = function ( ALT )
  1053.  {
  1054.    local (i)
  1055.  
  1056.    check_plot_object ();
  1057.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  1058.    if (exist (ALT)) 
  1059.    { 
  1060.      WIN.[P].alt[i] = ALT; 
  1061.    else
  1062.      WIN.[P].alt[i] = 60;
  1063.    }
  1064.    return P;
  1065.  };
  1066.  
  1067.  #
  1068.  # Set the viewing azimuth for 3-D plots
  1069.  #
  1070.  
  1071.  plaz = function ( AZ )
  1072.  {
  1073.    local (i)
  1074.  
  1075.    check_plot_object ();
  1076.    i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
  1077.    if (exist (AZ)) 
  1078.    { 
  1079.      WIN.[P].az[i] = AZ; 
  1080.    else
  1081.      WIN.[P].az[i] = 45;
  1082.    }
  1083.    return P;
  1084.  };
  1085.  
  1086.  ##############################################################################
  1087.  #
  1088.  # Various internal support functions. Eventually these will be static.
  1089.  #
  1090.  ##############################################################################
  1091.  
  1092.  #
  1093.  # Find the X and Y scales for a single matrix.
  1094.  #
  1095.  
  1096.  xy_scales = function ( M, p, xmin, xmax, ymin, ymax )
  1097.  {
  1098.  
  1099.    #
  1100.    # 1st check for un-plottable data
  1101.    #
  1102.  
  1103.    if (any (any (isinf (M))))
  1104.      { error ("plot: cannot plot infs"); }
  1105.    if (any (any (isnan (M))))
  1106.      { error ("plot: cannot plot NaNs"); }
  1107.  
  1108.    if (M.nc == 1)
  1109.    {
  1110.      xmin = 1;
  1111.      xmax = M.nr;
  1112.      ymin = min (M);
  1113.      ymax = max (M);
  1114.    else
  1115.      xmin = min (M[;1]);
  1116.      xmax = max (M[;1]);
  1117.      ymin = min (min (M[;2:M.nc]));
  1118.      ymax = max (max (M[;2:M.nc]));
  1119.    }
  1120.  
  1121.    #
  1122.    # Check computed scale limits against user's
  1123.    #
  1124.  
  1125.    if (!isinf (WIN.[P].xmin[p])) { xmin = WIN.[P].xmin[p]; }
  1126.    if (!isinf (WIN.[P].xmax[p])) { xmax = WIN.[P].xmax[p]; }
  1127.    if (!isinf (WIN.[P].ymin[p])) { ymin = WIN.[P].ymin[p]; }
  1128.    if (!isinf (WIN.[P].ymax[p])) { ymax = WIN.[P].ymax[p]; }
  1129.  
  1130.    #
  1131.    # Check for potential errors
  1132.    #
  1133.  
  1134.    if (xmin == xmax) 
  1135.    { 
  1136.      xmin = xmin - 1;
  1137.      xmax = xmax + 1;
  1138.    }
  1139.  
  1140.    if (ymin == ymax)
  1141.    {
  1142.      ymin = ymin - 1;
  1143.      ymax = ymax + 1;
  1144.    }
  1145.  
  1146.    #
  1147.    # Finally, adjust if log-scales
  1148.    #
  1149.  
  1150.    if (find_char (WIN.[P].gridx[p], "l"))
  1151.    {
  1152.      if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log <= 0"); }
  1153.      xmin = log10 (xmin);
  1154.      xmax = log10 (xmax);
  1155.    }
  1156.    if (find_char (WIN.[P].gridy[p], "l"))
  1157.    {
  1158.      if (ymin <= 0 || ymax <= 0) { error ("plot: cannot plot log <= 0"); }
  1159.      ymin = log10 (ymin);
  1160.      ymax = log10 (ymax);
  1161.    }
  1162.  
  1163.    return 1;
  1164.  };
  1165.  
  1166.  #
  1167.  # Find the X, Y and Z scales for a single matrix.
  1168.  #
  1169.  
  1170.  xyz_scales = function ( L, p, xmin, xmax, ymin, ymax, zmin, zmax )
  1171.  {
  1172.    # X - scale
  1173.    if (any (any (isinf (L.x))))
  1174.      { error ("plot3: cannot plot infs"); }
  1175.    if (any (any (isnan (L.x))))
  1176.      { error ("plot3: cannot plot NaNs"); }
  1177.    
  1178.    xmin = min (real (L.x));
  1179.    xmax = max (real (L.x));
  1180.  
  1181.    # Y - scale
  1182.    if (any (any (isinf (L.y))))
  1183.      { error ("plot3: cannot plot infs"); }
  1184.    if (any (any (isnan (L.y))))
  1185.      { error ("plot3: cannot plot NaNs"); }
  1186.    
  1187.    ymin = min (real (L.y));
  1188.    ymax = max (real (L.y));
  1189.  
  1190.    # Z - scale
  1191.    if (any (any (isinf (L.z))))
  1192.      { error ("plot3: cannot plot infs"); }
  1193.    if (any (any (isnan (L.z))))
  1194.      { error ("plot3: cannot plot NaNs"); }
  1195.  
  1196.    zmin = min (min (real (L.z)));
  1197.    zmax = max (max (real (L.z)));
  1198.  
  1199.    #
  1200.    # Check computed scale limits against user's
  1201.    #
  1202.  
  1203.    if (!isinf (WIN.[P].xmin[p])) { xmin = WIN.[P].xmin[p]; }
  1204.    if (!isinf (WIN.[P].xmax[p])) { xmax = WIN.[P].xmax[p]; }
  1205.    if (!isinf (WIN.[P].ymin[p])) { ymin = WIN.[P].ymin[p]; }
  1206.    if (!isinf (WIN.[P].ymax[p])) { ymax = WIN.[P].ymax[p]; }
  1207.    if (!isinf (WIN.[P].zmin[p])) { zmin = WIN.[P].zmin[p]; }
  1208.    if (!isinf (WIN.[P].zmax[p])) { zmax = WIN.[P].zmax[p]; }
  1209.  
  1210.    return 1;
  1211.  };
  1212.  
  1213.  #
  1214.  # Find the X and Y scales for a list of matrices
  1215.  #
  1216.  
  1217.  list_scales = function ( data, p, Xmin, Xmax, Ymin, Ymax )
  1218.  {
  1219.    local (M, i, xmin, xmax, ymin, ymax, once)
  1220.    once = 1;
  1221.  
  1222.    for (i in members (data))
  1223.    {
  1224.      M = real (data.[i]);
  1225.      if (class (M) != "num") { continue; }
  1226.  
  1227.      #
  1228.      # 1st check for un-plottable data
  1229.      #
  1230.  
  1231.      if (any (any (isinf (M))))
  1232.        { error ("plot: cannot plot infs"); }
  1233.      if (any (any (isnan (M))))
  1234.        { error ("plot: cannot plot NaNs"); }
  1235.  
  1236.      if (M.nc == 1)
  1237.      {
  1238.        xmin = 1;
  1239.        xmax = M.nr;
  1240.        ymin = min (M);
  1241.        ymax = max (M);
  1242.      else
  1243.        xmin = min (M[;1]);
  1244.        xmax = max (M[;1]);
  1245.        ymin = min (min (M[;2:M.nc]));
  1246.        ymax = max (max (M[;2:M.nc]));
  1247.      }
  1248.      if (once) { 
  1249.        Xmin = xmin; Xmax = xmax; Ymin = ymin; Ymax = ymax; 
  1250.        once = 0; 
  1251.      }
  1252.      if (xmin < Xmin) { Xmin = xmin; }
  1253.      if (xmax > Xmax) { Xmax = xmax; }
  1254.      if (ymin < Ymin) { Ymin = ymin; }
  1255.      if (ymax > Ymax) { Ymax = ymax; }
  1256.    }
  1257.  
  1258.    #
  1259.    # Check computed scale limits against user's
  1260.    #
  1261.  
  1262.    if (!isinf (WIN.[P].xmin[p])) { Xmin = WIN.[P].xmin[p]; }
  1263.    if (!isinf (WIN.[P].xmax[p])) { Xmax = WIN.[P].xmax[p]; }
  1264.    if (!isinf (WIN.[P].ymin[p])) { Ymin = WIN.[P].ymin[p]; }
  1265.    if (!isinf (WIN.[P].ymax[p])) { Ymax = WIN.[P].ymax[p]; }
  1266.  
  1267.    #
  1268.    # Finally, adjust if log-scales
  1269.    #
  1270.  
  1271.    if (find_char (WIN.[P].gridx[p], "l"))
  1272.    {
  1273.      if (Xmin <= 0 || Xmax <= 0) { error ("plot: cannot plot log x <= 0"); }
  1274.      Xmin = log10 (Xmin);
  1275.      Xmax = log10 (Xmax);
  1276.    }
  1277.    if (find_char (WIN.[P].gridy[p], "l"))
  1278.    {
  1279.      if (Ymin <= 0 || Ymax <= 0) { error ("plot: cannot plot log y <= 0"); }
  1280.      Ymin = log10 (Ymin);
  1281.      Ymax = log10 (Ymax);
  1282.    }
  1283.  
  1284.    return 1;
  1285.  };
  1286.    
  1287.  #
  1288.  # Find the maximum number of elements in a bin for a single 
  1289.  # column matrix.
  1290.  #
  1291.  
  1292.  hist_scales = function ( data, nbin )
  1293.  {
  1294.    local (i, binval, dmin, dmax, dbin)
  1295.  
  1296.    dmin = min (real (data));
  1297.    dmax = max (real (data));
  1298.    dbin = linspace (dmin, dmax, nbin+1);
  1299.    binval = zeros (nbin, 1);
  1300.  
  1301.    for (i in 1:nbin)
  1302.    {
  1303.      binval[i] = length (find (data >= dbin[i] && data < dbin[i+1]));
  1304.    }
  1305.  
  1306.    return max (binval);
  1307.  };
  1308.  
  1309.  #
  1310.  # Plot the columns of a matrix (core function)
  1311.  #
  1312.  
  1313.  plot_matrix = function ( M, p, K )
  1314.  {
  1315.    local (ans, i, k, l, np, x, y)
  1316.  
  1317.    np = M.nr;
  1318.   
  1319.    if (M.nc == 1)
  1320.    {
  1321.      x = 1:M.nr;
  1322.      y = real (M);
  1323.      k = mod (1+K, 14) + 1;
  1324.      l = mod (1+K, 8) + 1;
  1325.  
  1326.      if (find_char (WIN.[P].gridx[p], "l"))
  1327.        { x = log10 (x); }
  1328.      if (find_char (WIN.[P].gridy[p], "l"))
  1329.        { y = log10 (y); }
  1330.  
  1331.      _plcol (WIN.[P].color[p;k]);
  1332.      _pllsty (WIN.[P].lstyle[p;l]);
  1333.  
  1334.      if (WIN.[P].style[p] == "line") {
  1335.        _plline (M.nr, x, y);
  1336.      else if (WIN.[P].style[p] == "point") {
  1337.        _plpoin (M.nr, x, y, WIN.[P].pstyle[p]+k);
  1338.      else if (WIN.[P].style[p] == "line-point") {
  1339.        _plline (M.nr, x, y);
  1340.        _plpoin (M.nr, x, y, WIN.[P].pstyle[p]+k);
  1341.      }}}
  1342.  
  1343.    else
  1344.  
  1345.      #
  1346.      # Check for large column dimension
  1347.      #
  1348.  
  1349.      if (M.nc > M.nr)
  1350.      {
  1351.        printf (" Plot %i columns and %i rows, are you sure (y/n) ? "...
  1352.                , M.nc, M.nr);
  1353.        ans = getline ("stdin");
  1354.        if (ans.[1] != "y") { return -1; }
  1355.      }
  1356.  
  1357.      for (i in 2:M.nc)
  1358.      {
  1359.        x = real (M[;1]);
  1360.        y = real (M[;i]);
  1361.        if (find_char (WIN.[P].gridx[p], "l"))
  1362.          { x = log10 (x); }
  1363.        if (find_char (WIN.[P].gridy[p], "l"))
  1364.          { y = log10 (y); }
  1365.  
  1366.        k = mod (i-1 + K, 14) + 1;
  1367.        l = mod (i-1 + K, 8) + 1;
  1368.  
  1369.        _plcol (WIN.[P].color[p;k]);
  1370.        _pllsty (WIN.[P].lstyle[p;l]);
  1371.  
  1372.        if (WIN.[P].style[p] == "line") {
  1373.          _plline (np, x, y);
  1374.        else if (WIN.[P].style[p] == "point") {
  1375.          _plpoin (np, x, y, WIN.[P].pstyle[p]+k);
  1376.        else if (WIN.[P].style[p] == "line-point") {
  1377.          _plline (np, x, y);
  1378.          _plpoin (np, x, y, WIN.[P].pstyle[p]+k);
  1379.        }}}
  1380.       
  1381.      }
  1382.    }
  1383.  
  1384.   return k;
  1385.  };
  1386.  
  1387.  #
  1388.  # Plot all of the matrices in a list on the same plot
  1389.  #
  1390.  
  1391.  plot_list = function ( L , p )
  1392.  {
  1393.    local (M, i, k)
  1394.    k = 0;
  1395.    for (i in members (L))
  1396.    {
  1397.      M = L.[i];
  1398.      if (class (M) != "num") { continue; }
  1399.      if ((k = plot_matrix (M, p, k)) < 0) { return k; }
  1400.    }
  1401.    return 1;
  1402.  };
  1403.  
  1404.  #
  1405.  # Check the elements of LIST.
  1406.  # LIST must contain elements `x', `y',
  1407.  # and `z'
  1408.  #
  1409.  
  1410.  check_3d_list = function ( LIST )
  1411.  {
  1412.    #
  1413.    # Check existence and types
  1414.    #
  1415.  
  1416.    if (class (LIST) != "list") {
  1417.      error ("plot3: argument must be a list");
  1418.    }
  1419.    if (!exist (LIST.x)) {
  1420.      error ("plot3: arg must contain `x' member");
  1421.    else if (class (LIST.x) != "num") {
  1422.      error ("plot3: x must be numeric");
  1423.    }}
  1424.    if (!exist (LIST.y)) {
  1425.      error ("plot3: arg must contain `y' member");
  1426.    else if (class (LIST.y) != "num") {
  1427.      error ("plot3: y must be numeric");
  1428.    }}
  1429.    if (!exist (LIST.z)) {
  1430.      error ("plot3: arg must contain `z' member");
  1431.    else if (class (LIST.z) != "num") {
  1432.      error ("plot3: z must be numeric");
  1433.    }}
  1434.  
  1435.    #
  1436.    # Check sizes
  1437.    #
  1438.  
  1439.    if (LIST.x.n != LIST.z.nr) {
  1440.      error ("plot3: x.n != z.nr");
  1441.    }
  1442.  
  1443.    if (LIST.y.n != LIST.z.nc) {
  1444.      error ("plot3: y.n != z.nc");
  1445.    }
  1446.  
  1447.  };
  1448.  
  1449.   find_char = function ( str , char )
  1450.   {
  1451.     local (i, tmp)
  1452.  
  1453.     tmp = strsplt (str);
  1454.     for (i in 1:tmp.n)
  1455.     {
  1456.       if (tmp[i] == char) 
  1457.       {
  1458.         return i;
  1459.       }
  1460.     }
  1461.     return 0;
  1462.   };
  1463.